package com.dfs.parent.gateway.filter;

import com.dfs.parent.common.core.constant.TokenConstant;
import com.dfs.parent.common.core.utils.ResponseUtil;
import com.dfs.parent.gateway.client.webclient.OrderServiceClient;
import com.dfs.parent.gateway.props.JwtProperties;
import com.dfs.parent.gateway.props.WhitelistUrlProperties;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @Description 网关鉴权
 * @Author dahong
 * @Date 2024/2/1 00:18
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AuthFilter  implements GlobalFilter, Ordered {
    /**
     * 请求各个微服务 不需要用户认证的URL
     */
    private final WhitelistUrlProperties whiteListUrlProperties;
    private final JwtProperties jwtProperties;
    private final OrderServiceClient orderServiceClient;
    @Autowired
    private WebClient.Builder webClientBuilder;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String path = exchange.getRequest().getURI().getPath();

//        Mono<Result> resultMono=orderServiceClient.getPort();
//        System.out.println("当前请求的端口号111===》："+resultMono);
//        return resultMono.flatMap(result ->{
//            System.out.println("当前请求的端口号2："+result.getData());
//            return chain.filter(exchange);
//        });
        return chain.filter(exchange);
        //1:不需要认证的url
//        if(isSkip(path)) {
//            return chain.filter(exchange);
//        }
//        ServerHttpRequest request = exchange.getRequest();
//        // 验证token是否有效
//        String token = getToken(request);
//        if(StrUtil.isBlank(token)){
//            return unauthorized(exchange, "没有携带Token信息！");
//        }
//        // 校验我们的jwt 若jwt不对或者超时都会抛出异常
//        Claims claims = JwtUtil.parseToken(token,jwtProperties.getSecret());
//
//        //第四步 把从jwt中解析出来的 用户登陆信息存储到请求头中
//        ServerWebExchange webExchange = wrapHeader(exchange,claims);
//        return chain.filter(webExchange);
    }
    /**
     * 方法实现说明:不需要授权的路径
     * @author:smlz
     * @param path 当前请求路径
     * @return:
     * @exception:
     * @date:2019/12/26 13:49
     */
    private boolean isSkip(String path) {
        //路径匹配器(简介SpringMvc拦截器的匹配器)
        //比如/oauth/** 可以匹配/oauth/token    /oauth/check_token等
        PathMatcher pathMatcher = new AntPathMatcher();
        for(String skipPath:whiteListUrlProperties.getWhiteUrls()) {
            if(pathMatcher.match(skipPath,path)) {
                return true;
            }
        }
        return false;
    }
    /**
     * 从请求头获取token
     * @param request ServerHttpRequest
     * @return token
     */
    private String getToken(ServerHttpRequest request) {
        String token = request.getHeaders().getFirst(TokenConstant.DFS_TOKEN);
        return token;
    }
    /**
     * 方法实现说明:把我们从jwt解析出来的用户信息存储到请求中
     * @author:smlz
     * @param serverWebExchange
     * @param claims
     * @return: ServerWebExchange
     * @exception:
     * @date:2020/1/22 12:12
     */
    private ServerWebExchange wrapHeader(ServerWebExchange serverWebExchange,Claims claims) {
        //向headers中放文件，记得build
        ServerHttpRequest request = serverWebExchange.getRequest().mutate()
                .header("userId",claims.get("userId").toString())
                .header("username",claims.get("username").toString())
                .build();
        //将现在的request 变成 change对象
        return serverWebExchange.mutate().request(request).build();
    }


    private Mono<Void> unauthorized(ServerWebExchange exchange, String msg) {
        log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
        return ResponseUtil.webFluxResponseWriter(exchange.getResponse(), MediaType.APPLICATION_JSON_VALUE, HttpStatus.UNAUTHORIZED.value(), msg);
    }



    @Override
    public int getOrder() {
        return -100; // 和 Spring Security Filter 的顺序对齐
    }
}
